﻿using System;
using System.Collections;
using System.Dynamic;

namespace TK
{
    public partial class CustomSerializer {
        
        bool writeValue(CustomSerializerState state, object value, string fieldName = null)
        {
            if (value == null) return false;

            var type = value.GetType();
            state.writeTypeName(type);

            TypeHandler handler;
            if (SimpleTypes.TryGetValue(type, out handler)) handler.Write(state, value);
            else if (type.IsArray) writeArray(state, (Array) value);
            else if (type.IsGenericType) writeGeneric(state, value);
            else if (type.IsEnum) writeEnum(state, value);
            else if (value is BitArray) writeBitArray(state, (BitArray) value);
            //else if (value is ExpandoObject) writeDynamic(state, (ExpandoObject) value);
            else
            {
                state.checkRings(value, fieldName);
                writeComplex(state, value);
            }
            return true;
        }

        object readValue(CustomSerializerState state, Type expectedType, Type ownerType, string propertyName, out bool success)
        {
            success = false;
            var typeName = state.readTypeName();
            if (string.IsNullOrEmpty(typeName)) return null;

            updateType(expectedType);
            var storedType = getTypeByName(typeName, state.settings.ClassMap);
            if (storedType == null) return null;

            TypeHandler handler;
            success = true;
            if (SimpleTypes.TryGetValue(storedType, out handler)) {
                var value = handler.Read(state);
                if (expectedType != storedType && expectedType!=typeof(object))
                    value = expectedType.IsArray && storedType.IsArray
                        ? convertArray((Array) value, expectedType.GetElementType(), ownerType, propertyName)
                        : convertValue(value, expectedType, ownerType, propertyName);
                return value;
            }

            if (storedType.IsArray || storedType.FullName == "System.Array")
                return readArray(state, storedType.IsGenericType ? storedType.GetGenericArguments()[0] : storedType.GetElementType(), ownerType, propertyName);

            if (storedType.IsGenericType) return !storedType.IsValueType ? readGeneric(state, storedType, ownerType, propertyName) : readNullable(state, storedType); // check this!
            if (storedType.IsEnum) return readEnum(state, storedType, expectedType);
            if (storedType == typeof (BitArray)) return readBitArray(state);
            //if (storedType == typeof (ExpandoObject)) return readDynamic(state, expectedType, ownerType, propertyName);

            var r = readComplex(state, expectedType == typeof(object) || storedType.IsSubclassOf(expectedType) ? storedType : expectedType); // convert storedType => expectedType ?
            return r;
        }
    }
}